VGA based Video display card
Looking back at posts, the first design of the VGA card was created in 2021. The original design goal was to have a VGA output in 640x480 resolution with text display and several different bitmap modes.
The initial version of the card didn’t have all the features I had planned, but it did support a bitmap framebuffer and a 80x30 text mode. There was some experimentation with palette bitmaps and large scrollable bitmaps that was reasonably successful but the design was limited.
I started on a clean re-write of the FPGA code when I did a redesign on the VGA card hardware. The hardware changes were minor but building on what I learnt on the original card allowed a much better overall design.
Adding hardware accelerated features to get EmuTOS working efficiently rekindled my interest in expanding the features I had envisioned for the initial version of the card — making it something I could use for a system able to develop games on. Initially I wanted a simple tilemap system and was hoping that I could display a few sprites as well. As features started developing I started pushing what the FPGA was capable of and have ended up exceeding what I thought I could do, arriving at a very capable video card.
Overview #
The GfxVGA card is an FPGA-based video display processor built around a Xilinx Spartan-6 (XC6SLX25). The card outputs VGA at 640x480 60Hz and connects to the 68000 CPU bus.
The video card supports text, bitmap, tiles and sprite display modes. It supports a resolution of 640x480 or 320x240 with up to 65,536 colours. There is 2MB of video RAM used for the bitmap framebuffer or for storing tile and sprite data.
The tile and sprite handling has been designed to work in a similar fashion to how arcade and console games in the 80s and 90s worked. The classic approach — storing a set of small tile images in VRAM and building up a scene by placing them on a grid — uses far less memory than a full-screen bitmap and allows smooth scrolling essentially for free in hardware. While each tile or sprite only has a 16-colour palette, each one can select from several independent palettes, allowing a wide variety of colours on screen at once.
EmuTOS runs well on the card, making use of the 640x40 RGB mode for the GEM desktop and the hardware drawing functions for fast screen updates. The drawing engine handles filled rectangles, lines and triangles directly in hardware, which keeps the 68000 free for other work.
Display Modes #
Text Mode #
- 80×30 character mode (8×16 font)
- 80×60 character mode (8×8 font)
- Hardware cursor
- Hardware controlled text blinking
- 16 total colours from a user defined palette
- 16/8 background colours — only 8 available when blink mode is enabled, otherwise the full 16
- Custom 8×16 or 8×8 fonts
Palette support #
There is a 1024-entry palette used by the bitmap, tiles, sprite and text modes. Each mode can select from several palette banks within the full palette range, allowing a wide range of colours across layers.
Bitmap mode #
- 640x480 and 320x240 resolutions
- RGB-565 mode (16-bit, 65,536 colours)
- palette modes
- 8-bpp 256 colors
- 4-bpp 16 colors
- 2-bpp 4 colors
- 1-bpp 2 colors
- Sprites can be used over bitmap modes
- Framebuffer pointer for double buffering
Tile Mode #
There are 4 tile layers supporting 8×8 or 16×16 tiles. Each tile uses 16 colours, and tiles can select from 8 independent palettes — giving 128 available colours per layer (120 usable, as index 0 is the transparency colour).
- Two 16×16 layers
- Two 8×8 layers
- Independent enable per layer
- 2048 tiles per layer
- Tile map area is 512×512 pixels
- 32×32 tiles for 16-pixel tiles
- 64×64 tiles for 8-pixel tiles
- Each tile layer supports independent per-pixel X/Y scrolling
- Palette selected from 8 16-colour palettes
- Selectable palette bank per tile layer from 8 palette banks
- Tile flipping on both X and Y axis
- Layer priority is linear — layers 1–4 draw in order
Sprites #
- 256 sprites available
- 48 visible sprites per scanline
- Flipping on X and Y axis
- Sprite priority control between sprites and tile layers
- 16 colours per sprite, index 0 always transparent
- 16 palette banks for 256 sprite colours
- Sprites can be displayed over bitmap modes, operating in 320×240 resolution
Hardware accelerated drawing #
The drawing engine operates directly on VRAM in 640x480 and 320x240 bitmap modes in RGB-565 format. The CPU writes the command parameters to the drawing registers and the hardware executes the operation, freeing the 68000 from having to plot pixels in software.
- Filled rectangle
- Line drawing
- General Bresenham line
- Fast horizontal line
- Fast vertical line
- Filled triangle
Memory operations:
- Memory fill
- Linear memory copy
- 2D memory copy
Testing the video capabilities #
Text modes #
80x30 text, 80x30 with a custom font, 80x60 mode
Bitmap modes #
16-bit (65,536 colours), 8-bpp (256 colours), 4-bpp (16 colours), 2-bpp (4 colours), 1-bpp (2 colours)
Hardware acceleration #
An example of hardware line and triangle drawing, a rotating cube with filled and wireframe modes.
Tiles and Sprites #
A demo to push the sprite limits. The ‘melt’ effect at the start is the hardware memory copy routines. The demo then has 4 tile layers, 1. the background starfield, 2. is the Y Ddraig logo, 3. is the scrolling text and 4. is the description text. Up to 256 sprites are displayed onscreen and demonstrates the sprite and tile priorities.